package com.horay.statemachiedemo.multi.builder;

import com.horay.statemachiedemo.multi.constant.StateMachineConstant;
import com.horay.statemachiedemo.multi.enums.OrderState;
import com.horay.statemachiedemo.multi.event.OrderEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.config.StateMachineBuilder;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.transition.Transition;

import java.util.EnumSet;

/**
 * Class description
 *
 * @author heyingcheng
 * @date 2020/10/23
 */
@Slf4j
@Configuration
public class OrderStateMachineBuilder {

    /**
     * 构建状态机
     *
     * @param beanFactory
     * @return
     * @throws Exception
     */
    public StateMachine<OrderState, OrderEvent> build(BeanFactory beanFactory) throws Exception {

        StateMachineBuilder.Builder<OrderState, OrderEvent> builder = StateMachineBuilder.builder();

        log.info("构建订单状态机");

        builder.configureConfiguration()
                .withConfiguration()
                .machineId(StateMachineConstant.ORDER_MACHINE_ID)
                .beanFactory(beanFactory)
                .listener(orderListener());

        builder.configureStates()
                .withStates()
                .initial(OrderState.UNPAID)
                .states(EnumSet.allOf(OrderState.class));

        builder.configureTransitions()
                .withExternal().source(OrderState.UNPAID).target(OrderState.WAITING_FOR_RECEIVE).event(OrderEvent.PAY).action(orderAction())
                .and()
                .withExternal().source(OrderState.WAITING_FOR_RECEIVE).target(OrderState.DONE).event(OrderEvent.RECEIVE);

        return builder.build();

    }

    @Bean
    public Action<OrderState, OrderEvent> orderAction() {
        return context -> log.info(String.valueOf(context));
    }

    @Bean
    public StateMachineListener<OrderState, OrderEvent> orderListener() {
        return new StateMachineListenerAdapter<OrderState, OrderEvent>() {

            @Override
            public void transition(Transition<OrderState, OrderEvent> transition) {
                if (transition.getTarget().getId() == OrderState.UNPAID) {
                    log.info("Listener:订单创建，待支付");
                    return;
                }

                if (transition.getSource().getId() == OrderState.UNPAID
                        && transition.getTarget().getId() == OrderState.WAITING_FOR_RECEIVE) {
                    log.info("Listener:用户完成支付，待收货");
                    return;
                }

                if (transition.getSource().getId() == OrderState.WAITING_FOR_RECEIVE
                        && transition.getTarget().getId() == OrderState.DONE) {
                    log.info("Listener:用户已收货，订单完成");
                    return;
                }
            }

        };
    }

}
